package com.spsy.product.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.spsy.common.core.utils.DateUtils;
import com.spsy.product.domain.Product;
import com.spsy.product.domain.ProductDetail;
import com.spsy.product.domain.vo.ProductVO;
import com.spsy.product.mapper.ProductDetailMapper;
import com.spsy.product.mapper.ProductMapper;
import com.spsy.product.service.IProductService;
import com.spsy.product.util.RedisKeyUtil;
import org.springframework.beans.BeanUtils;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ZSetOperations;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Set;

/**
 * 商品Service业务层处理
 * 
 * @author ruoyi
 * @date 2025-09-28
 */
@Service
public class ProductServiceImpl implements IProductService 
{


    @Resource
    private ProductMapper productMapper;

    @Resource
    private ProductDetailMapper productDetailMapper;

    @Resource
    private RedisTemplate<String, Object> redisTemplate;

    @Override
    @Transactional
    public ProductVO addProduct(Product product, ProductDetail detail) {
        // 1. 保存商品（设置创建时间）
        product.setCreateTime(new Date());
        product.setUpdateTime(new Date());
        productMapper.insert(product);

        // 2. 保存商品详情（关联商品ID + 设置时间）
        detail.setProductId(product.getId());
        detail.setCreateTime(new Date());
        detail.setUpdateTime(new Date());
        productDetailMapper.insert(detail);

        // 3. 转换为 VO 并同步到 Redis
        ProductVO productVO = convertToVO(product, detail);
        syncToRedis(productVO);

        return productVO;
    }

    @Override
    @Transactional
    public ProductVO updateProduct(Product product, ProductDetail detail) {
        // 1. 更新商品（设置更新时间）
        product.setUpdateTime(new Date());
        productMapper.updateById(product);

        // 2. 更新商品详情（关联商品ID + 设置更新时间）
        detail.setProductId(product.getId());
        detail.setUpdateTime(new Date());

        ProductDetail existingDetail = productDetailMapper.selectByProductId(product.getId());
        if (existingDetail != null) {
            detail.setId(existingDetail.getId());
            productDetailMapper.updateById(detail);
        } else {
            productDetailMapper.insert(detail);
        }

        // 3. 查询最新数据并转换为 VO
        Product updatedProduct = productMapper.selectById(product.getId());
        ProductDetail updatedDetail = productDetailMapper.selectByProductId(product.getId());
        ProductVO productVO = convertToVO(updatedProduct, updatedDetail);

        // 4. 同步到 Redis
        syncToRedis(productVO);

        return productVO;
    }

    @Override
    @Transactional
    public boolean deleteProduct(Long productId) {
        // 1. 逻辑删除商品
        Product product = new Product();
        product.setId(productId);
        product.setDeleted(1);
        productMapper.updateById(product);

        // 2. 逻辑删除商品详情
        ProductDetail detail = new ProductDetail();
        detail.setDeleted(1);
        QueryWrapper<ProductDetail> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("product_id", productId);
        productDetailMapper.update(detail, queryWrapper);

        // 3. 从 Redis 删除
        String productKey = RedisKeyUtil.getProductDetailKey(productId);
        redisTemplate.delete(productKey);

        // 4. 从价格排序的有序集合中删除
        String sortedSetKey = RedisKeyUtil.getProductSortedSetKey();
        redisTemplate.opsForZSet().remove(sortedSetKey, productId.toString());

        return true;
    }

    @Override
    public ProductVO getProductFromRedis(Long productId) {
        String key = RedisKeyUtil.getProductDetailKey(productId);
        return (ProductVO) redisTemplate.opsForValue().get(key);
    }

    @Override
    public Page<ProductVO> getProductPageFromRedis(int pageNum, int pageSize) {
        String sortedSetKey = RedisKeyUtil.getProductSortedSetKey();

        // 1. 获取总记录数
        Long total = redisTemplate.opsForZSet().size(sortedSetKey);

        // 2. 计算分页范围
        int start = (pageNum - 1) * pageSize;
        int end = pageNum * pageSize - 1;

        // 3. 获取分页的商品 ID（带价格排序）
        Set<ZSetOperations.TypedTuple<Object>> tuples = redisTemplate.opsForZSet()
                .rangeWithScores(sortedSetKey, start, end);

        // 4. 从 Redis 查询每个商品的详情
        List<ProductVO> productList = new ArrayList<>();
        if (tuples != null) {
            for (ZSetOperations.TypedTuple<Object> tuple : tuples) {
                String productIdStr = tuple.getValue().toString();
                Long productId = Long.parseLong(productIdStr);
                ProductVO productVO = getProductFromRedis(productId);
                if (productVO != null) {
                    productList.add(productVO);
                }
            }
        }

        // 5. 构建分页对象
        Page<ProductVO> page = new Page<>(pageNum, pageSize);
        page.setRecords(productList);
        page.setTotal(total != null ? total : 0);

        return page;
    }

    @Override
    public List<ProductVO> getTop5ByPriceDescFromRedis() {
        String sortedSetKey = RedisKeyUtil.getProductSortedSetKey();

        // 1. 获取价格倒序前 5 的商品 ID
        Set<ZSetOperations.TypedTuple<Object>> tuples = redisTemplate.opsForZSet()
                .reverseRangeWithScores(sortedSetKey, 0, 4);

        // 2. 从 Redis 查询每个商品的详情
        List<ProductVO> productList = new ArrayList<>();
        if (tuples != null) {
            for (ZSetOperations.TypedTuple<Object> tuple : tuples) {
                String productIdStr = tuple.getValue().toString();
                Long productId = Long.parseLong(productIdStr);
                ProductVO productVO = getProductFromRedis(productId);
                if (productVO != null) {
                    productList.add(productVO);
                }
            }
        }

        return productList;
    }

    // ---------- 工具方法 ----------

    // 商品 + 详情 转换为 VO
    private ProductVO convertToVO(Product product, ProductDetail detail) {
        ProductVO vo = new ProductVO();
        BeanUtils.copyProperties(product, vo);
        if (detail != null) {
            BeanUtils.copyProperties(detail, vo);
        }
        return vo;
    }

    // 同步商品数据到 Redis（普通缓存 + 价格排序的有序集合）
    private void syncToRedis(ProductVO productVO) {
        if (productVO == null) return;

        // 1. 普通缓存：商品详情（Key: product:detail:{id}）
        String detailKey = RedisKeyUtil.getProductDetailKey(productVO.getId());
        redisTemplate.opsForValue().set(detailKey, productVO);

        // 2. 有序集合：价格排序（Key: product:sorted:price，Score: 价格，Value: 商品ID）
        String sortedKey = RedisKeyUtil.getProductSortedSetKey();
        redisTemplate.opsForZSet().add(
                sortedKey,
                productVO.getId().toString(),
                productVO.getPrice().doubleValue()
        );
    }


    /**
     * 查询商品
     * 
     * @param id 商品主键
     * @return 商品
     */
    @Override
    public Product selectProductById(Long id)
    {
        return productMapper.selectProductById(id);
    }

    /**
     * 查询商品列表
     * 
     * @param product 商品
     * @return 商品
     */
    @Override
    public List<Product> selectProductList(Product product)
    {
        return productMapper.selectProductList(product);
    }

    /**
     * 新增商品
     * 
     * @param product 商品
     * @return 结果
     */
    @Override
    public int insertProduct(Product product)
    {
        product.setCreateTime(DateUtils.getNowDate());
        return productMapper.insertProduct(product);
    }

    /**
     * 修改商品
     * 
     * @param product 商品
     * @return 结果
     */
    @Override
    public int updateProduct(Product product)
    {
        product.setUpdateTime(DateUtils.getNowDate());
        return productMapper.updateProduct(product);
    }

    /**
     * 批量删除商品
     * 
     * @param ids 需要删除的商品主键
     * @return 结果
     */
    @Override
    public int deleteProductByIds(Long[] ids)
    {
        return productMapper.deleteProductByIds(ids);
    }

    /**
     * 删除商品信息
     * 
     * @param id 商品主键
     * @return 结果
     */
    @Override
    public int deleteProductById(Long id)
    {
        return productMapper.deleteProductById(id);
    }
}
